﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Data;
using System.Windows.Media.Imaging;
using System.Windows.Interop;
using System.Windows.Media;
using System.Drawing;

namespace DienLib.Converter
{
    public class WPFBitmapConverter
    {
        #region CACH 1
        /// <summary>
        /// Use ToImageSource instead
        /// </summary>
        /// <param name="value"></param>
        /// <param name="targetType"></param>
        /// <param name="parameter"></param>
        /// <param name="culture"></param>
        /// <returns></returns>
        public object Convert(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                if (value.GetType() == typeof(System.Drawing.Icon)) (value as System.Drawing.Icon).Save(ms);
                else ((System.Drawing.Bitmap)value).Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
                BitmapImage image = new BitmapImage();
                image.BeginInit();
                ms.Seek(0, SeekOrigin.Begin);
                image.StreamSource = ms;
                image.EndInit();

                return image;
            }
        }
        #endregion

        #region CACH 2
        /// <summary>
        /// Use ToImageSource instead
        /// </summary>
        /// <param name="bitmap"></param>
        /// <returns></returns>
        public BitmapSource Convert2(Bitmap bitmap)
        {
            if (bitmap == null)
                throw new ArgumentNullException("bitmap");

            if (System.Windows.Application.Current.Dispatcher == null)
                return null; // Is it possible?

            try
            {
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    // You need to specify the image format to fill the stream. 
                    // I'm assuming it is PNG
                    bitmap.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
                    memoryStream.Seek(0, SeekOrigin.Begin);

                    // Make sure to create the bitmap in the UI thread
                    if (InvokeRequired)
                        return (BitmapSource)System.Windows.Application.Current.Dispatcher.Invoke(
                            new Func<Stream, BitmapSource>(CreateBitmapSourceFromBitmap),
                            System.Windows.Threading.DispatcherPriority.Normal,
                            memoryStream);

                    return CreateBitmapSourceFromBitmap(memoryStream);
                }
            }
            catch (Exception)
            {
                return null;
            }
        }

        private static bool InvokeRequired
        {
            get { return System.Windows.Threading.Dispatcher.CurrentDispatcher != System.Windows.Application.Current.Dispatcher; }
        }

        private static BitmapSource CreateBitmapSourceFromBitmap(Stream stream)
        {
            BitmapDecoder bitmapDecoder = BitmapDecoder.Create(
                stream,
                BitmapCreateOptions.PreservePixelFormat,
                BitmapCacheOption.OnLoad);

            // This will disconnect the stream from the image completely...
            WriteableBitmap writable = new WriteableBitmap(bitmapDecoder.Frames.Single());
            writable.Freeze();

            return writable;
        }
        #endregion


        #region CACH 3 - PREFER
        /// <summary>
        /// Convert Unmanaged Icon to Managed ImageSource (Actually BitmapSource)
        /// </summary>
        /// <param name="icon"></param>
        /// <returns></returns>
        public ImageSource ToImageSource(Icon icon)
        {
            if (icon == null) throw new ArgumentNullException("icon");
            lock (icon) // lock for MultiThreading
            {
                IntPtr hIcon = icon.Handle; // Call GetHbitmap in multi-thread need lock

                try
                {
                    return System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
                        hIcon,
                        System.Windows.Int32Rect.Empty,
                        BitmapSizeOptions.FromEmptyOptions());
                }
                finally
                {
                    WinAPI.DeleteObject(hIcon);
                }
            }
        }

        /// <summary>
        /// Convert Unmanaged Bitmap to Managed ImageSource (Actually BitmapSource)
        /// </summary>
        /// <param name="bitmap"></param>
        /// <returns></returns>
        public ImageSource ToImageSource(Bitmap bitmap)
        {
            if (bitmap == null) throw new ArgumentNullException("bitmap");
            lock (bitmap) // lock for MultiThreading
            {
                IntPtr hBitmap = bitmap.GetHbitmap(); // Call GetHbitmap in multi-thread need lock

                try
                {
                    return System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                        hBitmap,
                        IntPtr.Zero,
                        System.Windows.Int32Rect.Empty,
                        BitmapSizeOptions.FromEmptyOptions());
                }
                finally
                {
                    WinAPI.DeleteObject(hBitmap);
                }
            }
        }
        #endregion
    }
}

